package com.hyk.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hyk.domain.SysMenu;
import com.hyk.domain.SysPrivilege;
import com.hyk.domain.SysRoleMenu;
import com.hyk.domain.SysRolePrivilege;
import com.hyk.mapper.SysRolePrivilegeMapper;
import com.hyk.model.RolePrivilegesParam;
import com.hyk.service.SysMenuService;
import com.hyk.service.SysPrivilegeService;
import com.hyk.service.SysRoleMenuService;
import com.hyk.service.SysRolePrivilegeService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;

@Service
public class SysRolePrivilegeServiceImpl extends ServiceImpl<SysRolePrivilegeMapper, SysRolePrivilege> implements SysRolePrivilegeService{

    @Resource
    private SysMenuService sysMenuService;

    @Resource
    private SysPrivilegeService sysPrivilegeService;

    @Resource
    private SysRoleMenuService sysRoleMenuService;

    @Resource
    private SysRolePrivilegeService sysRolePrivilegeService;

    @Override
    public List<SysMenu> findSysMenu(Long roleId) {

        //所有的菜单
        List<SysMenu> source = sysMenuService.list();
        //所有权限
        List<SysPrivilege> priSource = sysPrivilegeService.list();
        //所有该角色的权限
        QueryWrapper<SysRolePrivilege> wrapper = new QueryWrapper<>();
        wrapper.eq("role_id",roleId);
        List<SysRolePrivilege> roleSource = list(wrapper);


        List<SysMenu> top = new ArrayList<>();
        List<SysMenu> resultList = new ArrayList<>();

        //获取所有顶级菜单节点
        for (SysMenu sysMenu: source) {
            if(sysMenu.getParentId() == null){
                top.add(sysMenu);
            }
        }

        //获取一级菜单下有权限的子节点
        for (SysMenu sysMenu: top) {
            getChildren(source,priSource,sysMenu.getId(),roleSource,resultList);
        }
        return resultList;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void grantPrivileges(RolePrivilegesParam rolePrivilegesParam) {

        List<SysMenu> menuList = sysMenuService.list();

        //删除用户原有的所有权限
        sysPrivilegeService.removeByRoleId(rolePrivilegesParam.getRoleId());
        //删除用户原有的所有菜单
        sysRoleMenuService.removeByRoleId(rolePrivilegesParam.getRoleId());

        //用户所有权限id
        String[] privilegesId = rolePrivilegesParam.getPrivilegeIds();
        List<Long> privileges = new ArrayList<>();
        for (String id: privilegesId) {
            Long pid = Long.parseLong(id);
            privileges.add(pid);
        }
        //角色权限
        List<SysRolePrivilege> sysRolePrivileges = new ArrayList<>();
        long roleId = Long.parseLong(rolePrivilegesParam.getRoleId());

        for (Long privilegeId: privileges) {
            SysRolePrivilege sysRolePrivilege = new SysRolePrivilege();
            sysRolePrivilege.setRoleId(roleId);
            sysRolePrivilege.setPrivilegeId(privilegeId);
            sysRolePrivileges.add(sysRolePrivilege);
        }
        //通过权限id查找对应的menuId
        Set<Long> menuIds = sysPrivilegeService.findMenuIdByPrivilegeId(privileges);
        List<Long> menuIdList = new ArrayList<>();
        menuIdList.addAll(menuIds);

        for (Long menuId: menuIdList) {
            getParentMenu(menuIds,menuList,menuId);
        }

        List<SysRoleMenu> sysRoleMenus = new ArrayList<>();
        for (Long menuId: menuIds) {
            SysRoleMenu sysRoleMenu = new SysRoleMenu();
            sysRoleMenu.setMenuId(menuId);
            sysRoleMenu.setRoleId(roleId);
            sysRoleMenus.add(sysRoleMenu);
        }

        sysRolePrivilegeService.saveBatch(sysRolePrivileges);
        sysRoleMenuService.saveBatch(sysRoleMenus);

    }

    private void getParentMenu(Set<Long> menuIds,List<SysMenu> menuList,Long menuId) {
        Long parentId = findParentId(menuId,menuList);
        if(parentId == null){
            return;
        }
        menuIds.add(parentId);
        getParentMenu(menuIds,menuList,parentId);
    }

    private Long findParentId(Long menu, List<SysMenu> menuList) {
        for (SysMenu m: menuList) {
            if(m.getId().equals(menu)){
                return m.getParentId();
            }
        }
        return null;
    }


    //获取权限
    private void getChildren(List<SysMenu> source, List<SysPrivilege> priSource, Long id,
                                      List<SysRolePrivilege> roleSource,List<SysMenu> resultList) {

        List<SysMenu> childrenList = getChildrenMenu(source,id);
        if(childrenList.size() == 0){
            return ;
        }
        for (SysMenu sysMenu:childrenList) {
            //如果不为空，查询该menu是否有权限
            List<SysPrivilege> privileges = new ArrayList<>();
            for (SysPrivilege sysPrivilege: priSource) {
                if(sysMenu.getId().equals(sysPrivilege.getMenuId())){
                    privileges.add(sysPrivilege);
                }
            }
            //如果不为空，判定角色是否有该权限并返回
            if(!(privileges.size() == 0)){
                for (SysRolePrivilege sysRolePrivilege: roleSource) {
                    for (SysPrivilege sysPrivilege: privileges) {
                        if(sysRolePrivilege.getPrivilegeId().equals(sysPrivilege.getId())){
                            sysPrivilege.setOwn(1);
                            break;
                        }
                    }
                }
                sysMenu.setPrivileges(privileges);
                resultList.add(sysMenu);
            }
            getChildren(source,priSource,sysMenu.getId(),roleSource,resultList);
        }

    }
    //获取子节点
    private List<SysMenu> getChildrenMenu(List<SysMenu> source, Long id) {
        List<SysMenu> list = new ArrayList<>();
        for (SysMenu sysMenu: source) {
            if(Objects.equals(sysMenu.getParentId(), id)){
                list.add(sysMenu);
            }
        }
        return list;
    }
}
